
# ifndef __DFX_VERTEX_MANAGER_OGL_H__
# define __DFX_VERTEX_MANAGER_OGL_H__

# include <GL/glew.h>
# include <GL/GL.h>

# include "dfxVertexManager.h"
# include "dfxRenderData.h"
# define MAX_ID     9999

namespace DFX
{
    class VertexManager_OGL;

    class VertexCache_OGL
    {
    private:

        GLuint              mVAOHandle;
        GLuint              mVBHandle;
        GLuint              mIBHandle;
        GLuint              mIndexType;
        
        UInt32              mFormatId;
        UInt32              mMaxNumVertices;
        UInt32              mMaxNumIndices;
        UInt32              mNumVertices;
        UInt32              mNumIndices;
        UInt32              mVertexSize;

        VertexManager_OGL   *mManager;
        Material            *mMaterial;

    public:

        VertexCache_OGL(VertexManager_OGL *manager, UInt32 formatId, UInt32 maxNumVertices, 
            UInt32 maxNumIndices,  UInt32 vertexSize, UInt32 indexSize);

        ~VertexCache_OGL();

        UInt32 GetFormatId() const
        {
            return mFormatId;
        }

        UInt32 GetMaxNumVertices() const
        {
            return mMaxNumVertices;
        }

        UInt32 GetMaxNumIndices() const
        {
            return mMaxNumIndices;
        }

        UInt32 GetNumVertices() const
        {
            return mNumVertices;
        }

        UInt32 GetNumIndices() const
        {
            return mNumIndices;
        }

        Material* GetMaterial() const
        {
            return mMaterial;
        }

        bool IsEmpty() const
        {
            return mNumVertices == 0;
        }

        bool UsesMaterial(Material *m) const
        {
            return mMaterial == m;
        }

        void SetMaterial(Material *material);

        DFXRESULT Add(UInt32 numVertices, UInt32 numIndices,
            const void *vertices, const void *indices);

        DFXRESULT Render();
    };

    typedef std::vector<VertexCache_OGL*>   VertexCacheArray;
    typedef VertexCacheArray::iterator      VertexCacheIterator;

    class VertexManager_OGL : public VertexManager
    {
    private:

        VertexFormatArray   mVertexFormats;
        VertexCacheArray    mVertexCaches;
        RenderDataArray     mRenderDatas;
        MaterialArray       mMaterials;
        UInt32              mActiveFormatId;                

    public:

        VertexManager_OGL(GraphicsDevice *gd, UInt32 numCaches);
        ~VertexManager_OGL();

        UInt32 GetActiveFormatId() const
        {
            return mActiveFormatId;
        }        

        void SetActiveFormatId(UInt32 id)
        {
            mActiveFormatId = id;
        }

        VertexFormat* GetVertexFormat(UInt32 formatId);

        DFXRESULT AddVertexFormat(VertexFormat *format, UInt32 *formatId,
            UInt32 maxNumVertices, UInt32 maxNumIndices);

        DFXRESULT CreateBuffer(UInt32 formatId, Material *material, UInt32 numVertices, 
            UInt32 numIndices, UInt32 indexSize, const void *vertices, const void *indices, UInt32 *bufferId);

        DFXRESULT Render(UInt32 formatId, Material *material, UInt32 numVertices, 
            UInt32 numIndices, const void *vertices, const void *indices);

        DFXRESULT RenderVertices(UInt32 numVertices, const void *vertices,
            Material *material);

        DFXRESULT Render(UInt32 bufferId);

        DFXRESULT Render(UInt32 bufferId, Material *material, UInt32 startIndex, 
            UInt32 numVertices, UInt32 numTris);

        DFXRESULT RenderPoints(UInt32 formatId, UInt32 numVertices,
            const void *vertices, const Color4 &color);

        DFXRESULT RenderLines(UInt32 formatId, UInt32 numVertices,
            const void *vertices, const Color4 &color);

        DFXRESULT RenderLine(const Vector3 &start, const Vector3 &end,
            const Color4 &color);

        DFXRESULT ForcedRender(UInt32 formatId);
        DFXRESULT ForcedRenderAll();

        void InvalidateStates();
    };
}

# endif